Визуальное моделирование для профессионалов
Блок Engee Function
Блок Engee Function позволяет использовать код на языке Julia в моделях Engee.
Блок находится в библиотеке Базовые -> Пользовательские функции.
С помощью блоков Engee Function можно создавать элементы модели, которые ведут себя согласно заданному алгоритму. Эти блоки имеет смысл использовать в следующих случаях:
- если у вас уже есть нужный, протестированный алгоритм в виде кода на Julia или если вам легко его написать самостоятельно;
- если алгоритм на Julia написать легче, чем создать его из графических компонентов;
- если поведение нужного вам блока не задано ни одним из существующих блоков Engee или его невозможно задать при помощи графических блоков.
Примечание
В блоке Engee Function допустимо использовать большую часть возможностей языка Julia. При этом использование в блоке пакетного менеджера Pkg не предусматривается.
Использование
Для интеграции кода на Julia в модель Engee необходимо:
-
Добавить в модель блок Engee Function.
-
В окне настроек на вкладке Основные блока Engee Function нажать на кнопку Редактировать исходный код
для открытия редактора исходного кода (EngeeFunctionCode):
Ячейки исходного кода
Редактор исходного кода EngeeFunctionCode состоит из функциональных ячеек с кодом Julia. По умолчанию доступны три ячейки:
- информационная (нередактируемая);
- Component struct code;
- Step method code (последние две ячейки можно скрыть).
Для подключения дополнительных файлов исходного кода можно использовать функцию include() в ячейке Common code:
include("/user/engeefunction/source.jl")
Для добавления/удаления других функциональных ячеек нажмите на кнопку Управление методами
и установите/уберите флажки на нужных ячейках:
Каждая ячейка отвечает за уникальный функционал блока Engee Function.
-
Информационная ячейка (нередактируемая) — автоматически отображает переменные блока Engee Function, атрибуты входных и выходных сигналов (размерность, тип, дискретность) и другие параметры, заданные пользователем. Ее содержимое обновляется динамически в зависимости от настроек блока. Ячейка всегда активна, но не выбирается в меню управления методами
. Имеет полупрозрачный текст. -
Define component struct — добавляет ячейку Component struct code, в которой задается структура компонента блока Engee Function. Поля структуры определяются между нередактируемыми строками
struct Block <: AbstractCausalComponentиend. По умолчанию создается параметрg, инициализируемый значением блокаgain, а конструкторBlock()не принимает аргументов. -
Use common code — добавляет ячейку Common code, в которой пишется код в свободной форме. По умолчанию ячейка пуста. Например, если стандартное объявление структуры в Component struct code не подходит (из-за нередактируемости
struct Block <: AbstractCausalComponent), то можно отключить Define component struct, чтобы удалить ячейку, и определить структуру компонента вручную в Common code. То же самое касается любых функций из меню управления методами — вместо стандартных ячеек можно писать свой код в Common code.
Важно
Объявление компонента и функтора обязательно для работы Engee Function. Если Define component struct и Define step method отключены, то их код необходимо задать в Common code, иначе блок не будет работать.
-
Define step method — добавляет ячейку Step method code, в которой задается метод
Step, вычисляющий выходные сигналы блока Engee Function. Сигнатура метода генерируется автоматически в зависимости от значений соответствующих меток (Label) портов во вкладке Ports. Метод представлен в виде функтора и вызывается на каждом шаге симуляции. Поля определяются между нередактируемыми строкамиfunction (c::Block)(t::Real, in1)иend. Первый аргументt::Real— время симуляции, далее передаются переменные входных сигналов. Вычисленные значения выходов возвращаются через ключевое словоreturn. -
Define update method — добавляет ячейку Update method code, в которой метод
update!обновляет внутреннее состояние блока Engee Function на каждом шаге симуляции. Первый аргументc::Block— структура блока, второйt::Real— время симуляции, далее передаются входные сигналы. Если блок не имеет внутреннего состояния, то метод может оставаться пустым и просто возвращатьc. -
Define terminate method code — добавляет ячейку Terminate method code, которая выполняется при завершении симуляции блока Engee Function (с помощью метода
terminate!). Первый аргументc::Block— структура блока. По умолчанию метод не выполняет дополнительных действий и просто возвращаетc. -
Override type inheritance method — добавляет ячейку Types inheritance method, которая переопределяет метод наследования типов.
-
Use common method for types and dimensions inheritance — добавляет ячейку Common types and dimensions inheritance method, которая использует общий метод для переопределения наследования типов и размерностей одновременно.
-
Override sample time inheritance method — добавляет ячейку Sample times inheritance method, которая переопределяет метод наследования шага расчета.
-
Override direct feedthrough setting method — добавляет ячейку Direct feedthrough setting method, которая определяет прямое сквозное соединение.
Константы и функции получения атрибутов
Для того чтобы узнать типы, размеры и другую вспомогательную информацию в исполняемом коде блока, используйте следующие константы внутри вашего кода Engee Function:
-
BLOCK_NAME— имя блока. У каждого блока, добавленного на холст Engee, есть имя, по которому можно обратиться через эту константу. Например, можно обратиться кBLOCK_NAMEво время инициализации ошибки, чтобы вывести в ней имя блока. -
START_TIME— начало симуляции из настроек модели. -
STOP_TIME— конец симуляции из настроек модели. -
INPUT_SIGNAL_ATTRIBUTES— списки из атрибутов по каждому входному порту. Например, чтобы узнать атрибуты первого входного сигнала, используйтеINPUT_SIGNAL_ATTRIBUTES[1], где1— первый входной порт блока Engee Function. -
OUTPUT_SIGNAL_ATTRIBUTES— списки из атрибутов по каждому выходному порту. Например, чтобы узнать атрибуты первого выходного сигнала, используйтеOUTPUT_SIGNAL_ATTRIBUTES[1], где1— первый выходной порт блока Engee Function.
Чтобы узнать дополнительную информацию конкретного порта блока, можно обратиться к атрибутам его сигнала, добавив точку . после константы INPUT_SIGNAL_ATTRIBUTES[i], где [i] — номер входного порта, и OUTPUT_SIGNAL_ATTRIBUTES[i], где [i] — номер выходного порта соответственно. Можно узнать дополнительную информацию через следующие функции обращения:
dimensions— размерность сигнала. Можно сократить доdims.type— тип сигнала. Можно сократить доtp.sample_time— шаг расчета. Представляет собой структуру по аналогии с атрибутами сигналов, к которой можно обращаться через точку.. Доступны две функции обращения:period— период шага расчета. Полная функция обращения —sample_time.period. Можно сократить доst.p.offset— смещение шага расчета. Полная функция обращения —sample_time.offset. Можно сократить доst.o.direct_feedthrough— указывает, размыкает ли порт петли. Используется только для входных портов (проверяет атрибуты только для входного порта). Можно сократить доdf.
Диагностические функции
В исходном коде блока Engee Function также доступны функции warning, stop_simulation, pause_simulation и info, которые позволяют взаимодействовать с системой диагностики модели на этапе симуляции, позволяя выводить сообщения в окне диагностики
. Эти функции могут использоваться внутри следующих ячеек исходного кода:
- Component struct code
- Step method code
- Update method code
- Terminate method code
- Common code
Для корректной работы в ячейке Common code функции warning, stop_simulation, pause_simulation и info могут использоваться:
- внутри функций, переопределяющих поведение методов, отвечающих за выполнение модели, таких как
step,update!,terminate!; - внутри вспомогательных функций, которые вызываются из методов, отвечающих за выполнение модели. То есть если вспомогательная функция определена в Common code и используется, например, в
step, то вызовы диагностических функций внутри нее также будут выполняться корректно.
Рассмотрим подробнее сами диагностические функции:
warning— функцияwarning(msg::String)выводит предупреждающее сообщение. Симуляция при этом продолжается. Это может быть полезно для указания на некритичные проблемы или состояния, которые требуют внимания, но не останавливают выполнение. Пример:
if t == 5.0 || t == 7.5
warning("time == $t")
end
stop_simulation— функцияstop_simulation(msg::String)немедленно завершает симуляцию и выводит сообщение о завершении. Используется для указания на критическое условие, при котором продолжение моделирования невозможно или нежелательно. Пример:
if t == 5.0
stop_simulation("time == $t")
end
pause_simulation— функцияpause_simulation(msg::String)приостанавливает выполнение симуляции и отображает указанное сообщение о паузе. Возобновление симуляции возможно вручную с помощью кнопки Продолжить:
Эта функция может быть полезна для анализа состояния модели в интересующий момент времени. Пример:
if t == 5.0
pause_simulation("time == $t")
end
info— функцияinfo(msg::String)выводит информационное сообщение. Используется для отображения промежуточных значений без влияния на выполнение симуляции. Пример:
if t == 5.0 || t == 7.5
info("time == $t")
end
Параметры блока
Вкладка Основные
- Number of input ports — определяет количество входных портов.
- Number of output ports — определяет количество выходных портов.
- Sample time — интервал между шагами расчета. Чтобы наследовать шаг расчета, установите для этого параметра значение
−1.
Вкладка Advanced
- Use external cache for non-scalar output — использовать внешний кэш для нескалярных выходных сигналов. Используется, если у блока Engee Function только один выходной порт. Если флажок установлен, то выходной сигнал сможет принимать дополнительный аргумент
cache, который необходимо учесть в исходном коде EngeeFunctionCode. - Sample time inheritance method — определение метода наследования шага расчета в зависимости от выбранного значения.
Вкладка Parameters (настройка параметров)
- Number of parameters — число параметров, используемых в блоке.
- Parameter — определяет параметр для использования в исходном коде блока Engee Function. В параметре можно задать:
Name— имя параметра;Value— значение параметра.
В качестве переменных вкладки Parameters можно задавать глобальные переменные, доступные в окне переменных.
Вкладка Ports (порты)
-
Input Port — входной порт. Он настраивается с помощью следующих опций:
- Label — имя входного порта. По умолчанию ячейка Label не заполнена.
- Type — тип данных входного сигнала. Выберите один из вариантов:
- определенный тип (все, кроме
Inherit) — проверяется, что на входной порт подается сигнал определенного типа. Поддерживаемые типы данных:Float16,Float32,Float64,ComplexF32,ComplexF64,Bool,Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128. Inherit(по умолчанию) — наследует тип данных от связанного блока. Может быть любым типом данных.
- определенный тип (все, кроме
- Size — размерность входного сигнала:
- Наследование всех размерностей (
-1по умолчанию) — наследует размерность поданного на входной порт сигнала. - Определенные размерности — входной сигнал должен иметь заданное количество элементов. Размерности указываются в Julia-нотации (в виде кортежа), например
(2,)для одномерного сигнала из двух элементов или(2, 3, 4)для многомерного. Если указано-1, то размерность наследуется. - Наследование одной из размерностей — наследует размерность поданного на входной порт сигнала с явным указанием структуры данных. Например,
(-1, 2)— первая размерность наследуется, а вторая задается явно.
- Наследование всех размерностей (
- Output bus type — входной тип шины, заменяет размерность входного сигнала Size в случае, если у типа данных входного сигнала Type выбран тип
BusSignal(шина). По умолчанию имеет значениеBusSignal{(), Tuple{}, ()}. Чтобы блок Engee Function понял, какая шина придет на вход, достаточно установить Type в значениеInherit. Явное указание типа необходимо только для выходного сигнала. - Direct feedthrough — определяет прямое сквозное соединение:
- Если флажок установлен (по умолчанию), то доступно прямое сквозное соединение. Это означает, что выходной сигнал контролируется непосредственно значением входного порта.
- Если флажок снят, то прямое сквозное соединение недоступно. Это означает, что выходной сигнал не контролируется значением входного порта и позволяет блоку размыкать петли.
-
Output port — выходной порт. Он настраивается с помощью опций, аналогичных опциям входного порта.
Больше о работе с блоком Engee Function вы можете узнать в документации.
Практическая часть
Пример
Рассмотрим модель, содержащую блок Engee Function. Она находится в файле Engee Function.engee:
Блок Constant подает вектор чисел на блок Engee Function, в котором вычисляются математическое ожидание и среднее квадратическое отклонение этого вектора с помощью следующего кода:
Свойства блока Engee Function и настройка его входных и выходных портов показаны на рисунках:
- В свойствах блока (вкладка Основные) заданы один входной и два выходных сигнала.
- В свойствах портов (вкладка Ports) указано, что входной порт под названием
xбудет иметь размерность-1(унаследованную от предшествующего блока при компиляции модели), размерность двух выходных сигналов с именамиMиsigmaуказывается как()— это размерность скаляра. - На вкладке Parameters указано, что дополнительных параметров, передаваемых в код, блок не имеет (количество равно
0).
Выходные порты блока Engee Function подключены к блокам Terminator (заглушкам). Блок Display используется для вывода на экран результатов симуляции в числовом виде.
✏️Задание 1
Откройте и запустите модель, содержащую блок Engee Function:
- Откройте модель
Engee Function.engee. - Запустите модель. На блоке Display прочитайте значение математического ожидания
M. - Чтобы вывести на экран значение среднего квадратического отклонения
sigma, откройте окно настроек блока Display, после этого щелкните левой кнопкой мыши по сигналуsigmaв модели. Этот сигнал появится в списке сигналов. Щелкните на Подключение рядом с сигналомsigma.
- На блоке Display прочитайте значение среднего квадратического отклонения
sigma.
Решение
Результаты моделирования:
✏️Задание 2
Создайте модель, которая с помощью блока Engee Function вычисляет объем цилиндра на основе входных значений радиуса основания и высоты :
- Создайте новую модель. Добавьте в модель следующие блоки:
- Constant (2 шт., один со значением константы, равным
10, второй —25); - Engee Function;
- Terminator;
- Display.
- В окне настроек блока Engee Function задайте:
- во вкладке Основные число входных портов равным
2; - во вкладке Parameters число параметров равным
0; - во вкладке Ports имя первого входного порта (параметр Label) —
r, имя второго входного порта —h, имя выходного порта —V.
- Откройте окно редактора исходного кода блока Engee Function. В ячейке Step method code в теле функции вместо имеющегося по умолчанию кода введите код
return pi * r^2 * h. В ячейке Component struct code удалите код, находящийся там по умолчанию:
g::Real
function Block()
new(gain)
end
-
Блок Constant со значением
10соедините с входным портомrблока Engee Function, блок Constant со значением25— с входным портомhблока Engee Function, а блок Terminator — с выходным портом блока Engee Function. -
Откройте окно настроек блока Display, включите режим подключения сигналов, щелкните левой кнопкой мыши на выходной сигнал блока Engee Function. Этот сигнал появится в списке сигналов. Щелкните на Подключение рядом с сигналом
Engee Function.1. -
Запустите модель и на блоке Display прочитайте значение объема цилиндра, рассчитанного при и .
Решение
Модель:
Результаты моделирования: